#include <memory.h>

#define LAND_BASE_CORE

#include "land_base.h"

static struct {
	LandRef gc;
	LandRef* gcEnd;
}ctx = { 0 };

int
landInitRefContext(LandBase* config) {
	ctx.gcEnd = &ctx.gc;
	return 0;
}

LAND_BASE_API void*
landNewRef(size_t size, LandRefFree free) {
	LandRef* ref = malloc(size);
	memset(ref, 0, size);
	ref->ref = 1;
	ref->free = free;
	ref->gcNext = NULL;
	(*ctx.gcEnd).gcNext = ref;
	ctx.gcEnd = ref;
	return ref;
}

LAND_BASE_API void
landFreeRef(void* p) {
	LandRef* ref = (LandRef*)p;
	if (ref->ref <= 0) {
		return;
	}
	ref->ref = 0;
	if (ref->free) {
		ref->free(ref);
	}
	free(ref);
}

LAND_BASE_API int
landRetainRef(void* ref) {
	((LandRef*)ref)->ref++;
	return ((LandRef*)ref)->ref;
}

LAND_BASE_API int
landReleaseRef(void* p) {
	LandRef* ref = (LandRef*)p;
	ref->ref--;
	if (ref->ref > 0) {
		return ref->ref;
	}
	if (ref->free) {
		ref->free(ref);
	}
	free(ref);
	return 0;
}

LAND_BASE_API int
landCountRef(void* ref) {
	return ((LandRef*)ref)->ref;
}

LAND_BASE_API void
landAutoGcRef() {
	LandRef* next = ctx.gc.gcNext;
	LandRef* temp;
	while (next) {
		temp = next->gcNext;
		landReleaseRef(next);
		next = temp;
	}
	ctx.gc.gcNext = NULL;
}
